desc:Audio Dubler v3 (with Filter EQ)

options:want_all_kb
// options:no_meter

/* - EUGEN27771 - */
import WaveDisplayForAudioDubler v1



// -- In-out sliders ------
slider1:0<-30,6,0.01> Sound Out dB
// -- Pan section ---------
slider3:0<-100,100,0.1> Pan
slider4:1<0,1,1{ON,OFF}> -Pan Corection
// -- Detector Sliders ----
slider6:-30<-60,0,0.01> Threshold Detector dB
slider7:6.2<3,12,0.01> Sensitivity Detector dB
// -- Detector Double Trpping --
slider9:0<-30,12,0.01> Input Detector Gain dB
slider10:400<20,2000,1> Triger Time ms
// --- Delay Section ---------
slider12:6<0.1,30,0.1> Min Delay ms
slider13:26<0.1,30,0.1> Max Delay ms
slider14:1<0.1,30,0.1> Next Delay ms

slider16:0<0,30,0.1> Delay L CrossFade ms
slider17:0<0,30,0.1> Delay R CrossFade ms

slider20: 0<0,1,0.01> CrossFade
// -- LP-HP Filter Section ------------------
slider22:LPFreq=6000<1000,20000,1>-Lowpass Hz
slider23:HPFreq=350<20,1000,1>-Hipass Hz

slider25:Preview=0<0,2,1{Normal Out, Filter Out, Normal Out+ Marker}>-Preview

////////////////////////////////////////////////////////////////////////////////////////
@init
//-- CrossFade section ---------------------------
AMP_dB = 8.68588963806504;
src_vol = tgt_vol = exp(0/AMP_DB);
src_pan = tgt_pan = 0.01*slider3;
//------------------------------------------------
ext_noinit = 1; // -- Отвечает за обновление при старт-стоп-е
envOut1 = 0;
envOut2 = 0;
retrig_cnt = 10^5;
det_velo_smpls = 1;

del_step = 1/1000*srate;

next_delay = 1; // изначальное значение дилея
n_d = 0; // локатор для смены направления прироста дилея
cf_time = 10; // время кросфейла в мс
cf_speed = 1/(cf_time/1000 * srate); // прирост за каждый сэмпл
delay_L = 0;
delay_R = 0;
pan_law = 6; // Заданно статичное значение (можно любое поставить, и отрицательное тоже)

//------------------------------------------------
attack1  = 1/1000;   //1<0.1,5,0.01>-1 attack(fast) ms
attack2  = 7/1000;   //7<2,50,0.1>-2 attack(slow) ms
release1 = 10/1000;  //10<0.1,50,0.1>-1 release ms
release2 = 15/1000;  //15<2,50,1>-2 release ms
// -- ga, gr coeff -----------
ga1 = exp(-1/(srate*attack1));
gr1 = exp(-1/(srate*release1));
ga2 = exp(-1/(srate*attack2));
gr2 = exp(-1/(srate*release2));

//-- GFX -----------------------------------------
R = 20; G = 20; B = 20;
gfx_clear = R+G*256+B*65536;
wave.Init(30,20,1015,250, 6000); // init wave - (x,y,w,h, mem_offs)

x = 0;
Trig = 0;
cf = 0;

//************************************************
//-- Simple Filter EUGEN27771 -------------------------------
//************************************************
/* type = 0 - LP filter; type = 1 - HP filter;
FreqHz = cutoffFreq in Hz;
samplerate - can be different from the global "srate" if need,
this can be useful in some cases
active = 1 - if FreqHz valid for filter type,
HP active, if HPFreq > 1
LP active, if LPFreq < 19999 */
function FilterB.SetValues(type, FreqHz, samplerate)
  local(sqr2, c, c2, csqr2, d)
  instance(active, ampIn0, ampIn1, ampIn2, ampOut1, ampOut2)
(
  active = (type == 0 && FreqHz < 19999) || (type == 1 && FreqHz > 1);
  active ? (
    type ? (
      // Hi Pass //
      sqr2 = 1.414213562;
      c = tan(($pi/samplerate) * FreqHz );
      c2 = c * c;
      csqr2 = sqr2 * c;
      d = (c2 + csqr2 + 1);
      ampIn0 = 1 / d;
      ampIn1 = -(ampIn0 + ampIn0);
      ampIn2 = ampIn0;
      ampOut1 = (2 * (c2 - 1)) / d;
      ampOut2 = (1 - csqr2 + c2) / d;
    ) : (
      // Low Pass //
      sqr2 = 1.414213562;
      c = 1 / tan(($pi/srate) * FreqHz );
      c2 = c * c;
      csqr2 = sqr2 * c;
      d = (c2 + csqr2 + 1);
      ampIn0 = 1 / d;
      ampIn1 = ampIn0 + ampIn0;
      ampIn2 = ampIn0;
      ampOut1 = (2 * (1 - c2)) / d;
      ampOut2 = (c2 - csqr2 + 1) / d;
    );
  );

);
//----------------------------
// Filter in = input sample
// Filter out = out sample
function FilterB.Apply(in)
  instance(active, ampIn0, ampIn1, ampIn2, ampOut1, ampOut2, dlyIn1, dlyIn2, dlyOut1, dlyOut2, out)
(
  out = in;
  active ? (
    out = (ampIn0 * in) + (ampIn1 * dlyIn1) + (ampIn2 * dlyIn2) - (ampOut1 * dlyOut1) - (ampOut2 * dlyOut2);
    dlyOut2 = dlyOut1;
    dlyOut1 = out;
    dlyIn2 = dlyIn1;
    dlyIn1 = in;
  );

  out;
);

///////////////////////////////////////////////////////////////////////////////////////
@slider
// --- Vol Pan Section -------
tgt_vol = exp(0/AMP_DB);
tgt_pan = 0.01*slider3;
panlaw = exp(pan_law/AMP_DB);
pancomp = (panlaw > 1.0 ? 1.0/panlaw : panlaw);
// --- Delay Section ---------

// -- IN-OUT sliders - values-----------
In_gain = 10^(slider9/20);
Dry_Out = 10^(slider1/20);

// -- Detector sliders - values --------
Threshold = 10^(slider6/20);
Sensitivity = 10^(slider7/20);
Retrig = (slider10/1000)*srate;
ThresholdDraw = abs((5^(slider6/30))/1.4);

//-- LP L-R channels ---------
LP.FilterB.SetValues(0, LPFreq, srate);
//-- HP L-R channels ---------
HP.FilterB.SetValues(1, HPFreq, srate);

////////////////////////////////////////////////////////////////////////////////////////
@sample

// -- Delay ------------------------------
min_delay >= 29*1000/srate ? ( // - Если меняем предельные значения дилеев в слайдерах, то тут тоже нужно!
  min_delay = 29*1000/srate;
);

max_delay <= 1*1000/srate ? (
  max_delay = 1*1000/srate;
);

min_delay >= max_delay ? (
  slider12 = (max_delay - del_step)*1000/srate;
  sliderchange(slider12);
  min_delay = floor(slider12/1000*srate);
);

max_delay <= min_delay ? (
  slider13 = (min_delay + del_step)*1000/srate;
  sliderchange(slider13);
  max_delay = floor(slider13/1000*srate);
);

min_delay = floor(slider12/1000*srate);
max_delay = floor(slider13/1000*srate);

slider20 = x;
sliderchange(slider20);

// -- Filter  -----------------------------
fltr_out = LP.FilterB.Apply((spl0+spl1)/2); // channels sum
fltr_out = HP.FilterB.Apply(fltr_out);


// -- Get Input ---------------------
input = fltr_out * In_gain;
envIn = abs(input); // abs input value for enelopes etc

// -- Env followers ------------------------------
envOut1 < envIn ? ( // fast enelope
  envOut1 = envIn + ga1*(envOut1-envIn)
) : (
  envOut1 = envIn + gr1*(envOut1-envIn)
);

envOut2 < envIn ? ( // slow enelope
  envOut2 = envIn + ga2*(envOut2-envIn)
) : (
  envOut2 = envIn + gr2*(envOut2-envIn)
);

// -- Trigger ------------------------------------
retrig_cnt > Retrig ? (
  envOut1 > Threshold && envOut1/envOut2 > Sensitivity ? (
    Trig = 1;
    retrig_cnt = 0;
    trig_mrk = 1.2;
    next_delay_s = (floor(next_delay*10000/srate))/10;
    slider14 = next_delay_s;
    sliderchange(slider14);
  );
) : (
  envOut2 = envOut1; // уравнивает огибающие
  retrig_cnt+=1;
);

//  Секция выдачи рандомного дилея
next_delay >= min_delay && n_d == 0 ? (
  next_delay += 1;
  next_delay >= max_delay ? (
    // next_delay = max_delay - 2;
    n_d = 1;
  );
) : (
  next_delay -= 1;
  next_delay <= min_delay ? (
    // next_delay = min_delay + 2;
    n_d = 0;
  );
);

next_delay < min_delay || next_delay > max_delay ? ( // нужно для того, чтобы отлавливать не корректные регулировки min-max дилея
  ext_1 = floor(min_delay+(max_delay-min_delay)/2);
  next_delay = ext_1;
  n_d = 0;
);

Trig == 1 ? (
  x >= 0 && cf == 0 ? (
    x += cf_speed;
    x >= 1 ? (
      x = 1;
      cf = 1;
      delay_L = next_delay_s;
      buflL = floor(delay_L/1000*srate); // === ofset-а нет
      slider16 = delay_L;
      sliderchange(slider16);
      Trig = 0;
    );
  ):(
    x -= cf_speed;
  );
  x <= 0 ? (
    x = 0;
    cf = 0;
    delay_R = next_delay_s;
    buflR = floor(delay_R/1000*srate) + 3000; // === 3000 -ofset
    slider17 = delay_R;
    sliderchange(slider17);
    Trig = 0;
  );
);

//=========================================================
// --- Vol Pan Section -------
d_pan = (tgt_pan-src_pan)/samplesblock;
tpan = src_pan;
src_pan = tgt_pan;
tpan += d_pan;
adj = 1;

panlaw != 1.0 ? (
  panlaw > 1.0 ? adj *= panlaw;
  panatt = abs(tpan);
  adj *= pancomp+(1.0-pancomp)*(2.0/(2.0-panatt)-1.0);
);

adj0 = adj1 = adj;
tpan < 0.0 ? adj1 *= 1.0+tpan;
tpan > 0.0 ? adj0 *= 1.0-tpan;

// --- Delay Section ---------
bufLpos[0] = spl1 ;
bufLpos = bufLpos + 1 ;
bufLpos >= buflL ? bufLpos = 0;

bufRpos[0] = spl1 ;
bufRpos = bufRpos + 1 ;
bufRpos >= buflR ? bufRpos = 3000;

spl0 *= adj0;
///////////////////////////////////////////////////////////////////////////////////////
Preview == 0 ? ( // 0 = Norm Out, 1 = filter out, 2 = Norm + Marker Out
  spl1 = bufLpos[0]*sqrt(1-x) + bufRpos[0]*sqrt(x);
  spl1 *= adj1;
  spl0*=Dry_Out;
  spl1*=Dry_Out;
);

Preview == 1 ? ( // 0 = Norm Out, 1 = filter out, 2 = Norm + Marker Out
  spl0 = input/2;
  spl1 = input/2;
);

Preview == 2 ? ( // 0 = Norm Out, 1 = filter out, 2 = Norm + Marker Out
  spl1 = bufLpos[0]*sqrt(1-x) + bufRpos[0]*sqrt(x);
  spl1 *= adj1;
  spl0*=Dry_Out;
  spl1*=Dry_Out;
  spl0 = spl0+trig_mrk;
  spl1 = spl1+trig_mrk;
);


// == For GFX =========================================== //

wave.Build(input, trig_mrk); // args = sample input and trig velo(if>0)
trig_mrk=0;

@gfx 1084 300
//-- Draw Wave ------------------
wave.redraw ? (
  wave.Draw_waveform(ThresholdDraw); // draw
  wave.redraw = 0;      // reset redraw state
);
//-----------------------------------------

char = gfx_getchar(); // -- без него не пашет перехват mod-keys!
